{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# 使用Pytorch 搭建神经网络进实现气温预测\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import torch\n",
    "import torch.optim as optim\n",
    "import warnings\n",
    "\n",
    "warnings.filterwarnings('ignore')\n",
    "%matplotlib inline"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "       Date  Temperature(Celsius)(high)  Temperature(Celsius)(avg)  \\\n",
      "0  2014-1-1                          12                          4   \n",
      "1  2014-1-2                           7                          0   \n",
      "2  2014-1-3                           9                          3   \n",
      "3  2014-1-4                           2                         -2   \n",
      "4  2014-1-5                           7                          0   \n",
      "\n",
      "   Temperature(Celsius)(low)  Dew Point(Celsius)(high)  \\\n",
      "0                         -2                       -12   \n",
      "1                         -6                        -6   \n",
      "2                         -2                        -7   \n",
      "3                         -6                        -4   \n",
      "4                         -7                        -5   \n",
      "\n",
      "   Dew Point(Celsius)(avg)  Dew Point(Celsius)(low)  Humidity(%)(high)  \\\n",
      "0                      -17                      -20                 44   \n",
      "1                       -9                      -13                 74   \n",
      "2                      -13                      -18                 64   \n",
      "3                       -7                       -9                 80   \n",
      "4                      -11                      -15                 80   \n",
      "\n",
      "   Humidity(%)(avg)  Humidity(%)(low)  ...  Visibility(km)(high)  \\\n",
      "0                19                 7  ...                    31   \n",
      "1                50                28  ...                    18   \n",
      "2                32                 9  ...                    31   \n",
      "3                68                44  ...                    10   \n",
      "4                51                15  ...                    31   \n",
      "\n",
      "   Visibility(km)(avg)  Visibility(km)(low)  Wind(km/h)(high)  \\\n",
      "0                   11                    5                32   \n",
      "1                    7                    3                18   \n",
      "2                   13                    5                18   \n",
      "3                    5                    2                11   \n",
      "4                    7                    3                18   \n",
      "\n",
      "   Wind(km/h)(avg)  Precipitation(mm)(high)  Precipitation(mm)(sum)  weather1  \\\n",
      "0               16                       47                     0.0       NaN   \n",
      "1                5                        -                     0.0       NaN   \n",
      "2                8                        -                     0.0       NaN   \n",
      "3                5                        -                     0.0       NaN   \n",
      "4               10                        -                     0.0       NaN   \n",
      "\n",
      "  weather2  weather3  \n",
      "0      NaN       NaN  \n",
      "1      NaN       NaN  \n",
      "2      NaN       NaN  \n",
      "3      NaN       NaN  \n",
      "4      NaN       NaN  \n",
      "\n",
      "[5 rows x 23 columns]\n",
      "(365, 23)\n"
     ]
    },
    {
     "data": {
      "text/plain": "       Temperature(Celsius)(high)  Temperature(Celsius)(avg)  \\\ncount                  365.000000                 365.000000   \nmean                    19.523288                  13.364384   \nstd                     11.249060                  10.937703   \nmin                     -2.000000                  -7.000000   \n25%                      9.000000                   3.000000   \n50%                     22.000000                  14.000000   \n75%                     30.000000                  23.000000   \nmax                     42.000000                  31.000000   \n\n       Temperature(Celsius)(low)  Dew Point(Celsius)(high)  \\\ncount                 365.000000                365.000000   \nmean                    7.542466                  6.580822   \nstd                    11.032742                 12.328479   \nmin                   -13.000000                -24.000000   \n25%                    -3.000000                 -4.000000   \n50%                     9.000000                  9.000000   \n75%                    18.000000                 18.000000   \nmax                    27.000000                 25.000000   \n\n       Dew Point(Celsius)(avg)  Dew Point(Celsius)(low)  Humidity(%)(high)  \\\ncount               365.000000               365.000000         365.000000   \nmean                  2.123288                -2.465753          78.630137   \nstd                  13.762452                15.056015          18.203299   \nmin                 -33.000000               -40.000000          19.000000   \n25%                  -9.000000               -14.000000          69.000000   \n50%                   3.000000                -2.000000          83.000000   \n75%                  15.000000                11.000000          94.000000   \nmax                  24.000000                23.000000         100.000000   \n\n       Humidity(%)(avg)  Humidity(%)(low)  Sea Level Press(hPa's)(high)  \\\ncount        365.000000        365.000000                    365.000000   \nmean          50.753425         23.753425                   1019.536986   \nstd           19.083953         17.474142                     10.026442   \nmin            8.000000          4.000000                   1001.000000   \n25%           37.000000          8.000000                   1010.000000   \n50%           50.000000         20.000000                   1019.000000   \n75%           65.000000         36.000000                   1028.000000   \nmax           93.000000         81.000000                   1039.000000   \n\n       Sea Level Press(hPa's)(avg)  Sea Level Press(hPa's)(low)  \\\ncount                   365.000000                   365.000000   \nmean                   1016.657534                  1013.934247   \nstd                       9.641969                     9.512055   \nmin                     996.000000                   993.000000   \n25%                    1008.000000                  1005.000000   \n50%                    1016.000000                  1014.000000   \n75%                    1025.000000                  1022.000000   \nmax                    1037.000000                  1034.000000   \n\n       Visibility(km)(high)  Visibility(km)(avg)  Visibility(km)(low)  \\\ncount            365.000000           365.000000           365.000000   \nmean              18.073973             9.504110             4.131507   \nstd               10.124907             6.458074             3.993019   \nmin                2.000000             1.000000             0.000000   \n25%                8.000000             5.000000             2.000000   \n50%               18.000000             7.000000             3.000000   \n75%               31.000000            13.000000             6.000000   \nmax               31.000000            31.000000            31.000000   \n\n       Wind(km/h)(high)  Wind(km/h)(avg)  Precipitation(mm)(sum)  \ncount        365.000000       365.000000              365.000000  \nmean          21.961644         8.942466                1.112027  \nstd           10.709894         4.651536                5.510722  \nmin            6.000000         3.000000                0.000000  \n25%           14.000000         6.000000                0.000000  \n50%           18.000000         8.000000                0.000000  \n75%           26.000000        10.000000                0.000000  \nmax           72.000000        34.000000               75.950000  ",
      "text/html": "<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Temperature(Celsius)(high)</th>\n      <th>Temperature(Celsius)(avg)</th>\n      <th>Temperature(Celsius)(low)</th>\n      <th>Dew Point(Celsius)(high)</th>\n      <th>Dew Point(Celsius)(avg)</th>\n      <th>Dew Point(Celsius)(low)</th>\n      <th>Humidity(%)(high)</th>\n      <th>Humidity(%)(avg)</th>\n      <th>Humidity(%)(low)</th>\n      <th>Sea Level Press(hPa's)(high)</th>\n      <th>Sea Level Press(hPa's)(avg)</th>\n      <th>Sea Level Press(hPa's)(low)</th>\n      <th>Visibility(km)(high)</th>\n      <th>Visibility(km)(avg)</th>\n      <th>Visibility(km)(low)</th>\n      <th>Wind(km/h)(high)</th>\n      <th>Wind(km/h)(avg)</th>\n      <th>Precipitation(mm)(sum)</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>count</th>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n      <td>365.000000</td>\n    </tr>\n    <tr>\n      <th>mean</th>\n      <td>19.523288</td>\n      <td>13.364384</td>\n      <td>7.542466</td>\n      <td>6.580822</td>\n      <td>2.123288</td>\n      <td>-2.465753</td>\n      <td>78.630137</td>\n      <td>50.753425</td>\n      <td>23.753425</td>\n      <td>1019.536986</td>\n      <td>1016.657534</td>\n      <td>1013.934247</td>\n      <td>18.073973</td>\n      <td>9.504110</td>\n      <td>4.131507</td>\n      <td>21.961644</td>\n      <td>8.942466</td>\n      <td>1.112027</td>\n    </tr>\n    <tr>\n      <th>std</th>\n      <td>11.249060</td>\n      <td>10.937703</td>\n      <td>11.032742</td>\n      <td>12.328479</td>\n      <td>13.762452</td>\n      <td>15.056015</td>\n      <td>18.203299</td>\n      <td>19.083953</td>\n      <td>17.474142</td>\n      <td>10.026442</td>\n      <td>9.641969</td>\n      <td>9.512055</td>\n      <td>10.124907</td>\n      <td>6.458074</td>\n      <td>3.993019</td>\n      <td>10.709894</td>\n      <td>4.651536</td>\n      <td>5.510722</td>\n    </tr>\n    <tr>\n      <th>min</th>\n      <td>-2.000000</td>\n      <td>-7.000000</td>\n      <td>-13.000000</td>\n      <td>-24.000000</td>\n      <td>-33.000000</td>\n      <td>-40.000000</td>\n      <td>19.000000</td>\n      <td>8.000000</td>\n      <td>4.000000</td>\n      <td>1001.000000</td>\n      <td>996.000000</td>\n      <td>993.000000</td>\n      <td>2.000000</td>\n      <td>1.000000</td>\n      <td>0.000000</td>\n      <td>6.000000</td>\n      <td>3.000000</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>25%</th>\n      <td>9.000000</td>\n      <td>3.000000</td>\n      <td>-3.000000</td>\n      <td>-4.000000</td>\n      <td>-9.000000</td>\n      <td>-14.000000</td>\n      <td>69.000000</td>\n      <td>37.000000</td>\n      <td>8.000000</td>\n      <td>1010.000000</td>\n      <td>1008.000000</td>\n      <td>1005.000000</td>\n      <td>8.000000</td>\n      <td>5.000000</td>\n      <td>2.000000</td>\n      <td>14.000000</td>\n      <td>6.000000</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>50%</th>\n      <td>22.000000</td>\n      <td>14.000000</td>\n      <td>9.000000</td>\n      <td>9.000000</td>\n      <td>3.000000</td>\n      <td>-2.000000</td>\n      <td>83.000000</td>\n      <td>50.000000</td>\n      <td>20.000000</td>\n      <td>1019.000000</td>\n      <td>1016.000000</td>\n      <td>1014.000000</td>\n      <td>18.000000</td>\n      <td>7.000000</td>\n      <td>3.000000</td>\n      <td>18.000000</td>\n      <td>8.000000</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>75%</th>\n      <td>30.000000</td>\n      <td>23.000000</td>\n      <td>18.000000</td>\n      <td>18.000000</td>\n      <td>15.000000</td>\n      <td>11.000000</td>\n      <td>94.000000</td>\n      <td>65.000000</td>\n      <td>36.000000</td>\n      <td>1028.000000</td>\n      <td>1025.000000</td>\n      <td>1022.000000</td>\n      <td>31.000000</td>\n      <td>13.000000</td>\n      <td>6.000000</td>\n      <td>26.000000</td>\n      <td>10.000000</td>\n      <td>0.000000</td>\n    </tr>\n    <tr>\n      <th>max</th>\n      <td>42.000000</td>\n      <td>31.000000</td>\n      <td>27.000000</td>\n      <td>25.000000</td>\n      <td>24.000000</td>\n      <td>23.000000</td>\n      <td>100.000000</td>\n      <td>93.000000</td>\n      <td>81.000000</td>\n      <td>1039.000000</td>\n      <td>1037.000000</td>\n      <td>1034.000000</td>\n      <td>31.000000</td>\n      <td>31.000000</td>\n      <td>31.000000</td>\n      <td>72.000000</td>\n      <td>34.000000</td>\n      <td>75.950000</td>\n    </tr>\n  </tbody>\n</table>\n</div>"
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "features = pd.read_csv('temps.csv')\n",
    "print(features.head())\n",
    "print(features.shape)\n",
    "features.describe()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 时间格式化\n",
    "import datetime\n",
    "\n",
    "years = features['year']\n",
    "months = features['month']\n",
    "days = features['day']\n",
    "\n",
    "dates = [f'{year}-{month}-{day}' for year,month,day in zip(years,months,days)]\n",
    "dates = [datetime.datetime.strptime(date,'%Y-%m-%d') for date in dates]\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[datetime.datetime(2014, 1, 1, 0, 0), datetime.datetime(2014, 1, 2, 0, 0), datetime.datetime(2014, 1, 3, 0, 0), datetime.datetime(2014, 1, 4, 0, 0), datetime.datetime(2014, 1, 5, 0, 0)]\n"
     ]
    }
   ],
   "source": [
    "import datetime\n",
    "dates = [datetime.datetime.strptime(date,'%Y-%m-%d') for date in features['Date']]\n",
    "print(dates[:5])"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "outputs": [
    {
     "data": {
      "text/plain": "<Figure size 720x720 with 4 Axes>",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAqkAAAKmCAYAAABucAcSAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAB5l0lEQVR4nO3de3xT9eH/8Xea3i+0UEq5g0DFgmAVBESFWZV5BUXqhW0iijeqww0dsOkYflVgyDZF4Kcic4g4GeKGTmWKVVQu3kBUFIvchba0UGhLr2l+f2AraU7aJE2bk+T1fDx8SE9Oks+nSU/e+VwtxcXFdgEAAAAmEubvAgAAAAANEVIBAABgOoRUAAAAmA4hFQAAAKZDSAUAAIDpEFIBAABgOoRUAAAAmA4hFQEtKSmp/r+dO3e6PO+aa66pP2/p0qWtWEIAAOANQioCXnh4uCRp2bJlhrfv2bNH77//fv15AADA/AipCHjt2rXTueeeq5deeknV1dVOt7/wwguy2+267LLL/FA6AADgDUIqgsLNN9+sw4cP64033nA4XlNToxdffFGDBg1S//79De+7detW/e53v9Pw4cPVo0cPpaam6pxzztHvf/97HT161OHcY8eOKSMjQykpKfr000+dHuvGG29UUlKSFi1a5LvKAQAQggipCApjx45VQkKCU5f/2rVrlZeXpwkTJri87z/+8Q+9+uqrOv300/XLX/5SEydOVIcOHbRo0SKNGjVKJSUl9ecmJibq73//uywWiyZOnKji4uL625566im99dZbuvzyyzV58mSf1xEAgFBCSEVQiIuL07hx45STk6N9+/bVH1+2bJni4+M1duxYl/f9zW9+o2+//VbPP/+8Hn30Uc2ZM0dvvfWW/vrXvyo3N1dLlixxOP/ss8/Wn/70J+3fv1/Z2dmSpM8++0yzZs1S165daUUFAMAHCKkIGhMmTFBtba1eeOEFSdIPP/ygd955R9ddd53i4+Nd3q979+6yWq1Ox2+55Ra1adNG7777rtNtkydP1uWXX67//ve/mjt3riZOnCi73a7nnntObdu29V2lAAAIUYRUBI2MjAwNHDhQL774omw2m1544QXZbLZGu/olqbq6Ws8884wuu+wy9ejRQ+3atVNSUpLatm2r48eP69ChQ4b3W7x4sbp27arZs2dr3759evDBBzV06NCWqBoAACGHNXkQVCZMmKCpU6dq7dq1Wr58uc4880ydc845jd5n4sSJev3119WzZ09deeWVSk1NVWRkpKSTQbSystLwfklJSRoxYoRWrFih2NhY3XLLLb6uDgAAIYuQiqCSlZWlhx56SA888IB++OEH3XfffY2ev2XLFr3++usaOXKkVq1apYiIiPrbamtr9eSTT7q875o1a7RixQolJyerqKhIU6ZM0T/+8Q9fVQUAgJBGdz+CSps2bXTttdfqhx9+UExMjLKysho9f9euXZKkK664wiGgSicnQ5WXlxveb8+ePbr33nuVmJiod999V6NGjdJ//vMfp0lWAADAO4RUBJ3f//73Wr58uV555RUlJiY2em737t0lSR9++KHD8cOHD+v+++83vE91dbVuu+02HTt2TAsWLFCPHj20ePFide7cWX/4wx+0bds231QEAIAQRnc/gk6XLl3UpUsXt84955xzNGzYML322msaNWqUhg0bpoKCAr3zzjtKS0tTp06dnO4zc+ZMffbZZ7r99ts1evRoSVJycrKWLFmiq6++Wrfeeqvee++9RlcUAAAAjaMlFSHNarXqpZde0m233aZDhw7p6aef1qZNm3TzzTfrlVdeUXi44/e4N998U4sWLdKAAQP0yCOPONw2fPhwzZgxQzt37tRvf/vb1qwGAABBx1JcXGz3dyEAAACAU9GSCgAAANMhpAJAgPnoo4904403Kj09XUlJSXrxxRebvM/XX3+tK664Qh07dlR6errmzp0ru52ONADmRUgFgABTVlamfv36ac6cOYqJiWny/OPHj+vaa69Vhw4d9O6772rOnDlasGCBnnrqqVYoLQB4h9n9ABBgRo0apVGjRkmSJk+e3OT5//rXv1ReXq7FixcrJiZG/fr103fffadFixbpnnvukcViaekiA4DHaEkFgCD38ccf67zzznNodb344ot16NAh7d27148lAwDXCKkAEOQKCgqUkpLicKzu54KCAn8UCQCaREgFgBDQsEu/btIUXf0AzIqQ+qPc3Fx/F8EtgVJOibK2pEAqbyCVVQq88rqjQ4cOTi2mhYWFkuTUwhoqgvF1bog6Br5gr19TCKkAEOSGDBmijRs3qqKiov5YTk6OOnXqpB49evixZADgGiEVAAJMaWmptm3bpm3btqm2tlYHDhzQtm3btH//fknSrFmzNHr06Przx40bp5iY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BQAAgOkQUgEgQC1ZskQDBw5UamqqRo4cqQ0bNjR6/tdff60rrrhCHTt2VHp6uubOnSu73d5KpQUAzxBSASAArV69WtOnT9fUqVO1fv16DRkyRFlZWdq/f7/h+cePH9e1116rDh066N1339WcOXO0YMECPfXUU61ccgBwDyEVAALQwoULNX78eE2YMEF9+/bVvHnzlJqaqqVLlxqe/69//Uvl5eVavHix+vXrpzFjxmjKlClatGgRrakATMlSXFzM1QkAAkhVVZU6deqk5557Ttdcc0398fvvv1/bt2/XG2+84XSfO++8U0ePHtXKlSvrj33++efKzMzU1q1b1bNnz1YoOQC4j5ZUAAgwRUVFstlsSklJcTiekpKigoICw/sUFBQYnl93GwCYDSEVAAKUxWJx+Nlutzsda+p8o+MAYAaEVAAIMMnJybJarU4toIWFhU6tpXU6dOhgeL4kl/cBAH8ipAJAgImMjFRGRoZycnIcjufk5Gjo0KGG9xkyZIg2btyoiooKh/M7deqkHj16tGh5AcAbhFQACEDZ2dlasWKFli1bph07dmjatGnKy8vTxIkTJUmzZs3S6NGj688fN26cYmJiNHnyZG3fvl1r1qzR3/72N02ePJnufgCmFO7vAgAAPDd27FgdOXJE8+bNU35+vtLT07Vy5Up1795dkpSXl6fdu3fXn5+YmKhXX31V999/vy666CIlJSUpOztb99xzj7+qAACNYgkqAAAAmA7d/QAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0/FLSP3oo4904403Kj09XUlJSXrxxRebvM/XX3+tK664Qh07dlR6errmzp0ru93eCqUFAHPhGgogFPglpJaVlalfv36aM2eOYmJimjz/+PHjuvbaa9WhQwe9++67mjNnjhYsWKCnnnqqFUoLAObCNRRAKAj3x5OOGjVKo0aNkiRNnjy5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vo51grluUvBfR4Px9Qv2a6gU/NdRrqGeMf0VateuXZo/f74eeeQRPf/885IUdBfW/fv366WXXtKCBQu0bt06SSdn2wbTAtvffPON+vXrp3/84x+Sgq9+X331lS6//HJ98sknDq1XwVTHHTt2aNKkSRo9erSuvvpqFRcXB93rKEkVFRWy2+2qrKz0d1F8Jtivo1xDg0OwX0e5hnrO1Fepb775RhdddJE+/vhjvfnmm/rb3/6m4cOH65tvvvF30Xzm66+/1s9//nOtXLlSTz75pB555BHNnz9fUnAtC/POO+/oxIkTeuihh/Tss8/WHw+GP869e/dq3LhxGjNmjP7v//5Pp512Wv1twfIafvPNN7r88svVtm1bXXLJJTpy5IjuuOMOScH1YfnNN9/o9ttv18UXX6xJkybpxRdf9HeRmi3Yr6NcQ4Pjby/Yr6NcQ71j2pBaWVmpBx98UFdffbVefvllvf3223rppZeUmJiorKwsffrpp5IC+w90z549uummm3TjjTdq5cqV2rRpk84991x9+OGHqq6u9nfxfComJkYXXHCBfvvb32rmzJl69tlnZbFYZLFYdOLECX8Xr1lycnJ09tln67HHHlNtba3+/Oc/6ze/+Y3uuusuffPNNwH/WpaVlel3v/udrrvuOj355JOaOnWqJk2apM6dO9efEwwfIt9//70uv/xydezYURdddJGSk5M1ZcoU3X///SouLvZ38bwS7NdRrqHBcQ2Vgvs6yjXU+2uoXyZOucNisejYsWO67LLLJEmxsbFKT0/XK6+8optuukmTJk3SO++8o/bt2wfkmI6amhqtXLlSGRkZmjJliqxWq5KTkzV+/HhdffXV2rVrl/r27evvYvrMsGHDtGHDBt10000qLCzUH//4RyUmJmrnzp3q06ePxo4dq/Bw074dG/XDDz8oISFBkjRq1CjFxMSoQ4cO2rVrl6666io98cQTuuqqqwLyfSqdvMAWFRXp5z//ef2x7777Tjk5OfrZz36msLAwzZw5UyNHjvRjKZtv9erVGjhwoObNmyfp5N/oqFGjdPvtt6u8vFx//etfFRkZ6edSeiaYr6NcQ4PnGioF93WUa6j311DTtqRGRkYqLCxM7733Xv0xm82m2NhYLV26VPHx8br33nslBe43kMTERF1yySVKTEysHx+WnJysiIgIw2+NtbW1rV1En7FYLNqyZYusVqumTp2qqVOnKjs7W/Pnz9fFF1+s8PDwgK2f1WrVjh07lJOTo+TkZK1YsULPPfeccnJyNHLkSE2fPl2lpaUB+z5NSkqSzWbTwoULtX37ds2aNUvPP/+8br/9dk2dOlUdO3bUXXfdpfz8fH8XtVkOHjwom81W/3NYWJiuvPJKLV++XKtWraq/8AaSYL+Ocg0NjmuoFNzXUa6h3l9DTRlS6/7QJk6cqO+//15LliyRdPJNbLPZlJycrLvuuku7d+/WwYMH/VlUr4WHh+uGG27QzTffLOmnOqekpCg5OdlhUsNrr70mKbAnOqSnp6tLly6yWq1q27attm3bppiYGEVEROi///2vpMCt369+9SvV1NTo97//vaSTrVVVVVWSpCeffFIVFRX1kzkCjd1uV2RkpB577DHt2bOn/uL6+OOP65577tHVV1+t5cuX68SJE/rPf/7j7+I2ywUXXKAvvvhCmzZtknTy/Wi325WZmak5c+boueee09atW/1bSA8E+3WUa2jwXEOl4L2Ocg1t3jXUlO/ouj+0zMxMnXnmmVq1alX94Fur1SpJ6tq1q8rKylRTU+O3cjZXUlKSpJNv4ro6l5eXq6SkpL5ejz76qG655Rbt27fPX8X0ibCwMEVFRemTTz5Rdna2Pv74Yz3//PO67777NGXKFL3wwgv+LqLX2rZtq6uuukqFhYUqKCiQ1WpVZGSk7Ha7SkpK1LFjx4DddrKu1eLiiy/Wxx9/rCeeeEJdu3bV4MGDJUnV1dUqKChQ9+7dHcZXBaKzzz5b5513nhYtWqSvvvrK4bYLL7xQkZGR+uGHH/xUOs+FwnWUa2hwXEOl4L2Ocg09ydtrqClDqnTyopOamqo//OEPSkpK0rJly/TYY49JkoqLi7V+/Xq1bdtWbdq08XNJm+/U7osTJ06orKxM0dHR+stf/lK/pErdAt2BqK6Fo2vXrrr55pu1YcMGvfzyy8rMzNTNN9+s3//+9y63cgwEsbGxuu2225SVlaVt27bphhtuUFFRkfbv36/ly5ervLxcPXv29Hcxmy0iIkLt27dXWFiYXn311frjL7zwgkpKSnTWWWf5sXTN16tXL91www3au3evnnzySW3durX+b7Nbt25KSUkJuMkboXId5Roa2NdQKTSuo1xDPb+G+n0x/5qaGtnt9vqFbaWfFpmu+//evXv17LPPavXq1SotLVXPnj118OBBvfLKKwHxojZWx4aOHz+uq666Sp07d9Z7772nN998U2effXZrFtcr7tRxy5Ytuv/++/X444871Mlms9W37JhVY/WrG8h/5MgR/fvf/9aTTz6pI0eOqEuXLiopKdGLL74YFO9Tu92u6upqzZ49W2+++aZqamrUu3dvff7551q1alVA1NGVUydjLF++XMuXL1d1dbXuuusude/eXa+//rpeeukl5eTkqFu3bn4urbNgv45yDT0pkK+hUvBfR7mG+v4a6teQ+u2332ru3LnKy8vTaaedpszMTI0bN07ST390dS9wWVmZiouLtXbtWqWmpqp///4B8a3KnTqeqqCgQAMGDFBERITefPNNDRgwwB/F9og7daz7f0VFhaKjo/1cYs+4U7+6P9Da2lpVVVXp3XffVUpKirp06RIQXTievE8LCwu1YcMGvffee+rZs6euvPJK9e7d219F90hNTY3LGdCnfpi8++67WrNmjZYvX15ft2eeecaUHyLBfh3lGhr411Ap+K+jXENb5hrqt5C6c+dOZWZm6rLLLtNpp52m9957T2VlZTrrrLO0cOFCSSfX+IuKivJH8XzCmzoWFxdr7ty5uu2229SnTx9/Fd1t3tQxUL71S7xPXdUxEJeB2blzp1auXKkbbrjB5QdCwwvwgQMHZLVaFR0drbZt27ZWUd0W7O9PrqGBfw2VeJ9KXEO9vYb6JaTa7XY9+uij+u6777Rs2TJJJ8cR/eMf/9CyZcuUnp6upUuX1p//1FNP6YorrlCvXr1au6he86aOl19+uXr37q3q6mqH7gKzCvbX0Zv6XXnllQ47pZhdsL+GdXbt2qVLL720fpeXyZMnq0ePHg7nGH1omHl/+2B/7biGBv5rKAX/dTQUXkPJf9dQv1x9LRaLDh486LAmWGxsrCZMmKA77rhD3333nWbNmiVJ+vTTT/XXv/5V9957b/14j0DgbR2rq6sDZkHmYH8dvanfPffcEzD1k4L/NZROLqT917/+VZdeeqn+8pe/6IUXXtCCBQu0d+9eh/PqLq6PPPKIpk6dKsncS/oE+2vHNTTwX0Mp+K+jofAa+vMa2up/yXVJ+6yzztKOHTu0fft29evXT9LJF3bs2LHauXOn3n//fRUXF2vw4MGaNWuWzj///IC58DSnjoHw7V8K/tcx2OsnhUYdpZMXyYEDB6pt27YaN26cUlJS6vfMvvfeex1aA4qLi7V79259/PHHOnz4sGmXvAn2145raOC/hlLw1zHY61fHn9dQv41J3b17ty655BJdeumlmjNnTv16d5KUl5en9PR0Pf/88xozZow/iucT1DHw6xjs9ZNCo45lZWWKi4ur/3nNmjW66667dNNNN2nKlCnq3r27bDabSkpKJEkVFRXq2LGjv4rrtmB/7YK9fhJ1DIY6Bnv9JP9dQ/0W5U877TT9/e9/V1ZWlmJjYzV9+nR16NBB0sm1xAYMGKB27dr5q3g+QR0Dv47BXj8pNOpYd3G12WwKCwvT6NGjZbfbdffdd8tisejuu+/Wc889p71792rp0qUOHzJmFuyvXbDXT6KOwVDHYK+f5L9rqF/bm0eMGKHnn39et9xyiw4dOqQxY8ZowIABWrlyZf0yDoGOOgZ+HYO9flJo1FFS/TI3tbW1GjNmjCwWi+655x698847OnDggNatWxdwM4yD/bUL9vpJ1DEY6hjs9avT2tdQvy/mL0lbt27Vgw8+qD179ig8PFwRERFasmSJKdck9BZ1DHzBXj8pNOpYp2482bXXXqutW7fqv//9b/14skAU7K9dsNdPoo7BINjrd6rWuIaaIqRKJ3cJOXr0qMrKypSamqrk5GR/F8nnqGPgC/b6SaFRR+lkt9VDDz2kxYsX64MPPtCZZ57p7yI1W7C/dsFeP4k6BoNgr1+d1riGmiakAkBrstlsevHFF5WRkaGBAwf6uzgAEFBa4xpKSAUQsgJx1xcAMIuWvoaad6VqAGhhBFQA8F5LX0MJqQAAADAdQioAAABMh5AKAAAA0yGkAgAAwHQIqQAAADAdQioAAABMh5AKAAAA0/n/kA8Ogo1vuKMAAAAASUVORK5CYII=\n"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 可视化\n",
    "plt.style.use('fivethirtyeight')\n",
    "fig, ((ax1,ax2),(ax3,ax4)) = plt.subplots(nrows=2,ncols=2,figsize=(10,10))\n",
    "fig.autofmt_xdate(rotation=45)\n",
    "\n",
    "# 标签\n",
    "ax1.plot(dates, features['Temperature(Celsius)(avg)'])\n",
    "ax1.set_xlabel('')\n",
    "ax1.set_ylabel('Temp'); ax1.set_title('Max')\n",
    "\n",
    "plt.tight_layout(pad=2)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 独热编码\n",
    "features = pd.get_dummies(features)  # 字符串值 列展开成行\n",
    "print(features.head())\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "labels = np.array(features['actual'])\n",
    "features = features.drop('actual', axis=1)\n",
    "feature_list = list(features.columns)\n",
    "features = np.array(features)\n",
    "print(features.shape) # 几个特征 ?\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 使用 sklearn 预处理\n",
    "from sklearn import  preprocessing\n",
    "input_feature = preprocessing.StandardScaler().fit_transform(features)\n",
    "print(input_feature[0])\n",
    "# 标准化后更容易收敛"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'input_feature' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mNameError\u001B[0m                                 Traceback (most recent call last)",
      "\u001B[1;32m<ipython-input-9-9d7e58dd918b>\u001B[0m in \u001B[0;36m<module>\u001B[1;34m\u001B[0m\n\u001B[0;32m      1\u001B[0m \u001B[1;31m# 构建神经网络 一种麻烦的方法\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      2\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 3\u001B[1;33m \u001B[0mx\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtorch\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mtensor\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0minput_feature\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdtype\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mfloat\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m      4\u001B[0m \u001B[0my\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mtorch\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mtensor\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mlabels\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdtype\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mfloat\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m      5\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
      "\u001B[1;31mNameError\u001B[0m: name 'input_feature' is not defined"
     ]
    }
   ],
   "source": [
    "# 构建神经网络 一种麻烦的方法\n",
    "\n",
    "x = torch.tensor(input_feature, dtype=float)\n",
    "y = torch.tensor(labels, dtype=float)\n",
    "\n",
    "# 权重\n",
    "weights = torch.randn((14,128), dtype=float, requires_grad=True) # 随机初始化参数\n",
    "biases = torch.randn(128, dtype=float, requires_grad=True)\n",
    "weights2 = torch.randn((128,1), dtype=float, requires_grad=True)\n",
    "biases2 = torch.randn(1, dtype=float, requires_grad=True)\n",
    "\n",
    "lr = 0.001\n",
    "losses = []\n",
    "epochs = 1000\n",
    "for epoch in range(epochs):\n",
    "    hidden = x.mm(weights) +  biases # 矩阵\n",
    "    hidden = torch.relu(hidden) # 激活函数\n",
    "    pred = hidden.mm(weights2) + biases2\n",
    "\n",
    "    loss = torch.mean((pred - y)**2) # 使用均分误差作为 损失值\n",
    "    if epoch % 100 == 0:\n",
    "        print(epoch, loss)\n",
    "    loss.backward() # 反向传播计算\n",
    "\n",
    "    # 更新参数\n",
    "    weights.data.add_(-lr * weights.grad.data)\n",
    "    biases.data.add_(-lr * weights.grad.data)\n",
    "    weights2.data.add_(-lr * weights2.grad.data)\n",
    "    biases2.data.add_(-lr * biases2.grad.data)\n",
    "    # 清空梯度\n",
    "    weights.grad.zero_()\n",
    "    biases.grad.zero_()\n",
    "    weights2.grad.zero_()\n",
    "    biases2.grad.zero_()\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 构建神经网络 一种麻烦的方法\n",
    "\n",
    "input_size = input_feature.shape[1]\n",
    "hidden_size = 128\n",
    "output_size = 1\n",
    "batch_size = 16\n",
    "net_nn = torch.nn.Sequential(torch.nn.Linear(input_size, hidden_size),\n",
    "                             torch.nn.Sigmoid(),\n",
    "                             torch.nn.Linear(hidden_size, output_size)\n",
    ")\n",
    "\n",
    "# 训练\n",
    "criterion = torch.nn.MSELoss(reduction='mean')\n",
    "optimizer = torch.optim.Adam(net_nn.parameters(), lr =0.001)\n",
    "losses = []\n",
    "epochs = 1000\n",
    "total_size = len(input_feature)\n",
    "for epoch in range(epochs):\n",
    "    for start in range(0, total_size, batch_size):\n",
    "        optimizer.zero_grad() # 梯度清零\n",
    "\n",
    "        end = start + batch_size if start+ batch_size < total_size else total_size\n",
    "        x = torch.tensor(input_feature[start:end],dtype=float, requires_grad=True)\n",
    "        y = torch.tensor(labels[start:end],dtype=float, requires_grad=True)\n",
    "        pred = net_nn(x)\n",
    "        loss = criterion(pred, y)\n",
    "        loss.backward(retain_graph=True)\n",
    "        optimizer.step()\n",
    "        losses.append(loss.data.numpy())\n",
    "\n",
    "    if epoch % 100 == 0:\n",
    "        print(epoch, losses)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 预测\n",
    "\n",
    "test_x = torch.tensor(input_feature, dtype=torch.float)\n",
    "pred = net_nn(test_x).data.numpy()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# 画图\n",
    "true_data = pd.DataFrame(data={'date': dates, 'actual': labels})\n",
    "pred_data = pd.DataFrame(data={'date': dates, 'prediction': pred.reshape(-1)})\n",
    "\n",
    "plt.plot(true_data['date'], true_data['actual'],'b-',label='actual')\n",
    "plt.plot(true_data['date'], true_data['prediction'],'ro',label='prediction')\n",
    "plt.xticks(rotation ='60')\n",
    "plt.legend()\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}